package jimmy.lottery;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Map.Entry;

public class Algorithm {

	public enum PREDICT_RESULT {
		/**
		 * 无效分组
		 */
		INVALID_GROUP,
		/**
		 * 命中
		 */
		SUCCESS,
		/**
		 * 未命中
		 */
		FAILURE
	}

	/**
	 * 历史记录开始索引
	 */
	int startIndex = 0;

	/**
	 * 历史记录步长
	 */
	int stepLen = 500;

	/**
	 * 随机数的生成个数
	 */
	int randomCount = stepLen + 1;

	/**
	 * 二分法分组方案生成数量
	 */
	int groupCount = 10 * 10 * 10 * 10 * 5;

	/**
	 * 随机数最大值
	 */
	byte maxNumber = 49;

	HashMap<String, List<Byte>> statusHashMap = null;
	HashMap<String, Short> limitHashMap1 = null;
	HashMap<String, Short> limitHashMap2 = null;
	HashMap<String, Short> tempHashMap1 = null;
	HashMap<String, Short> tempHashMap2 = null;
	HashMap<String, Short> candidateHashMap1 = null;
	HashMap<String, Short> candidateHashMap2 = null;
	HashMap<String, List<Byte>> groupHashMap = null;
	String candidateGroupName = "";

	String maxGroupName1 = "";
	String maxGroupName2 = "";
	short max1 = 0;
	short max2 = 0;
	static byte nextValue = 0;

	/**
	 * 最小分组连续极限(低于该连接极限的分组方案，将视为无效)
	 */
	byte minGroupLimit = 10;

	/**
	 * 下轮预测是否为正向分组(即：groupHashMap中存在的分组)
	 */
	boolean candidateUseLimit1 = false;

	/**
	 * 历史记录
	 */
	List<Byte> history = null;

	/**
	 * 随机生成器
	 */
	Random rnd = null;

	/**
	 * 当前位置索引
	 */
	int currentIndex = 0;

	/**
	 * 初始化历史记录
	 * 
	 * @throws Exception
	 */
	private void genHistory() throws Exception {

		String historyRecord = "22,14,45,42,39,37,17,47,26,35,33,40,16,1,13,12,1,14,11,28,9,20,43,13,27,31,5,4,3,39,35,23,22,47,9,39,15,40,27,28,24,21,28,11,34,2,17,32,8,24,34,28,8,34,13,7,41,28,20,37,5,44,30,36,18,37,1,2,45,12,37,33,8,21,4,41,15,35,30,10,36,2,40,5,19,29,25,22,2,17,13,38,19,1,41,45,34,1,28,42,18,21,33,38,46,1,17,8,9,15,42,4,24,46,15,24,20,29,6,49,48,23,46,16,29,18,24,35,15,36,43,30,17,32,33,36,20,35,18,7,42,28,33,43,43,27,3,36,48,35,18,12,42,26,6,29,11,37,29,26,49,12,47,11,2,38,49,30,47,39,21,7,38,22,39,23,32,7,4,26,1,44,29,10,38,24,6,34,9,47,12,11,3,38,24,24,10,41,28,21,22,38,34,3,24,40,12,38,8,1,15,36,24,42,29,43,43,5,45,22,5,19,49,14,34,11,46,27,44,27,1,36,23,6,43,1,19,4,11,8,13,38,11,4,7,37,19,1,6,3,18,15,42,48,37,17,8,32,3,35,30,10,45,26,34,42,48,17,33,23,21,37,35,2,36,12,22,3,29,39,12,9,31,48,45,12,32,47,7,36,45,9,45,31,43,26,38,34,15,24,10,25,22,15,37,38,12,9,49,14,49,42,39,47,29,40,47,41,49,10,28,40,14,33,14,16,19,12,29,10,32,22,31,23,11,6,41,36,38,6,17,42,11,21,10,41,5,6,37,48,10,31,3,24,42,10,23,26,25,20,40,19,12,40,10,21,13,31,6,14,34,35,15,27,44,17,23,11,6,24,4,40,35,29,10,23,24,26,2,33,17,24,13,18,30,22,26,1,37,19,23,46,33,19,5,3,12,48,45,13,14,6,49,10,5,13,31,34,8,5,2,1,6,41,15,47,32,8,38,19,10,10,2,13,26,33,27,24,44,11,4,27,3,10,21,42,17,42,45,17,5,2,29,44,4,3,17,8,5,25,13,3,40,4,6,41,18,21,18,42,35,14,18,10,42,44,47,25,34,48,9,7,39,17,18,33,14,18,27,5,45,20,35,29,1,25,7,38,28,27,19,33,40,27,43,5,23,3,22,18,27,6,4,11,20,20,9,24,2,44,32,3,19,33,36,47,13,43,4,35,46,12,17,22,26,35,40,43,38,23,44,9,4,6,30,37,40,10,19,37,20,24,36,10,40,9,36,9,18,10,44,37,23,44,26,28,8,17,48,37,12,19,31,6,41,22,29,35,18,23,36,43,5,49,34,29,47,7,19,10,17,5,26,15,13,2,19,3,2,6,14,47,40,18,12,40,8,17,15,43,16,19,5,18,41,19,18,41,9,33,41,10,26,42,33,8,23,30,20,41,39,11,10,30,47,33,21,35,11,8,37,6,30,4,15,17,39,45,32,18,16,34,22,41,30,31,20,45,17,46,41,43,18,5,29,8,15,30,14,47,44,14,45,41,4,11,41,43,42,41,13,14,48,43,16,10,42,19,15,30,16,38,17,28,36,3,1,7,46,29,32,46,8,2,41,14,45,48,20,14,42,2,24,49,24,13,32,10,49,27,24,47,15,10,38,38,20,9,11,37,33,42,22,15,40,15,35,43,13,12,7,17,32,32,7,13,4,46,30,47,22,23,34,33,20,32,21,16,49,33,34,41,12,17,13,17,34,7,6,46,37,41,5,10,46,31,6,13,7,37,15,34,38,16,5,11,38,17,49,45,40,2,48,17,12,26,19,27,11,49,34,34,25,1,36,13,7,45,21,2,29,29,43,26,41,4,6,8,39,15,47,40,47,10,26,44,32,33,43,8,4,14,15,3,22,43,26,23,24,41,29,39,29,10,39,8,36,47,35,18,28,31,3,48,13,45,13,36,27,29,17,7,28,49,8,40,32,23,4,31,31,43,24,23,5,20,9,21,9,35,8,17,39,40,29,40,31,49,15,45,6,36,13,30,10,48,3,13,15,24,25,38,24,5,1,14,36,32,11,3,2,2,8,48,6,6,28,25,40,26,10,43,6,35,20,46,41,44,10,22,18,12,35,5,34,42,45,33,46,30,31,34,15,9,5,41,27,31,7,24,14,37,39,9,39,25,39,4,43,11,42,35,10,49,7,13,41,48,8,12,1,35,20,13,43,13,10,46,18,9,26,19,7,31,42,30,37,37,12,49,36,4,38,42,20,35,8,36,8,6,8,44,25,2,26,15,45,36,9,5,12,10,43,22,21,19,47,14,30,34,14,1,35,5,49,5,24,23,7,39,35,10,47,14,32,23,40,2,4,22,20,31,11,2,1,3,25,34,38,36,13,46,45,20,45,24,4,26,20,2,26,41,31,19,39,44,20,31,44,11,20,24,42,33,4,42,48,37,16,39,34,40,4,38,31,15,48,47,34,26,26,38,24,19,21,10,14,28,4,7,26,48,35,7,15,36,48,23,44,30,41,17,14,21,45,24,21,26,7,4,24,4,31,21,45,41,18,10,38,10,49,23,14,19,6,27,42,10,1,41,27,40,16,2,2,28,40,41,13,14,7,16,44,19,3,1,46,46,47,46,16,16,20,21,48,30,31,36,17,42,29,20,41,30,8,35,40,17,33,19,32,17,11,8,3,24,15,44,20,9,32,17,14,49,41,27,18,30,26,6,1,10,24,43,11,14,37,44,24,2,49,19,49,27,13,24,31,33,42,24,22,22,22,42,7,37,23,34,43,16,35,28,45,37,42,41,38,47,27,5,12,6,34,25,47,5,46,27,6,12,2,27,27,13,41,37,18,8,32,46,27,15,17,18,48,35,19,23,14,35,8,42,9,34,27,14,37,10,40,10,23,7,36,11,12,12,3,40,43,4,38,10,2,37,48,37,20,48,46,9,21,19,17,12,16,30,45,40,5,44,49,29,30,10,22,28,21,9,20,20,15,13,29,43,32,11,9,22,12,10,28,45,28,35,38,47,3,36,5,22,6,30,48,31,8,35,4,23,10,8,17,18,38,35,22,46,2,39,38,42,19,38,13,27,37,30,15,29,36,35,20,22,21,10,34,30,36,31,24,34,48,10,7,12,1,40,2,30,6,42,29,17,32,16,22,25,42,13,6,38,13,5,47,33,46,23,13,14,40,47,44,49,47,10,43,49,48,33,35,29,35,21,5,32,14,29,5,31,25,1,34,31,32,5,2,24,41,5,1,38,10,2,30,12,47,14,1,31,41,15,49,47,7,47,43,48,25,8,15,17,37,22,47,13,5,32,43,34,12,6,15,37,41,34,38,8,18,42,14,44,6,41,25,4,23,2,45,14,38,22,3,8,35,41,4,32,40,33,41,34,7,46,38,37,37,9,6,32,9,24,28,39,47,24,1,20,44,37,3,43,27,3,29,13,31,32,5,1,7,12,10,48,16,28,8,45,48,5,27,45,38,38,3,29,37,43,43,42,39,40,47,28,32,13,9,16,35,4,40,26,6,21,28,1,19,2,41,42,43,25,31,21,30,13,31,13,10,6,47,4,48,38,24,14,48,34,49,2,14,23,40,45,39,7,48,7,13,11,26,1,24,5,28,32,22,13,37,32,47,18,34,7,15,21,17,37,5,2,28,4,12,18,8,34,27,11,43,17,5,4,25,39,2,18,48,9,48,6,19,9,36,14,33,36,13,22,27,17,34,36,6,38,27,23,7,2,30,28,5,1,44,39,30,39,22,17,14,13,17,49,8,42,25,44,34,20,30,21,49,42,48";
		String[] arrRecords = historyRecord.split(",");
		//System.out.println("历史数据长度:"+arrRecords.length);
		if (randomCount > arrRecords.length) {
			throw new Exception("randomCount值越界!");
		}
		history = new ArrayList<Byte>();
		for (int i = 0; i < randomCount; i++) {
			history.add(Byte.parseByte(arrRecords[i]));
		}

		// Random rnd = new Random();
		// for (int i = 0; i < randomCount; i++) {
		// int t = rnd.nextInt(maxNumber + 1);
		// if (t == 0) {
		// t = 1;
		// }
		// history.add((byte) t);
		// }
	}

	/**
	 * 初始化分组方案
	 */
	private void genGroup() {

		//System.out.println("开始生成分组=>");
		groupHashMap.clear();
		for (int i = 1; i <= groupCount; i++) {
			String groupKey = "G" + i;
			groupHashMap.put(groupKey, new ArrayList<Byte>());
			for (int j = 0; j < maxNumber / 2; j++) {
				int t = rnd.nextInt(maxNumber + 1);
				if (t <= 0) {
					t = 1;
				}
				while (groupHashMap.get(groupKey).contains((byte) t)) {
					t = rnd.nextInt(maxNumber + 1);
					if (t <= 0) {
						t = 1;
					}
				}
				groupHashMap.get(groupKey).add((byte) t);
			}

			// Byte[] bytes = new Byte[] { 1, 6, 11, 13, 15, 17, 20, 23, 24, 27,
			// 30, 31, 32, 33, 34, 36, 37, 38, 40, 41, 44, 46, 47, 48 };
			// for (Byte b : bytes) {
			// groupHashMap.get(groupKey).add(b);
			// }
			Collections.sort(groupHashMap.get(groupKey));
			// System.out.println(groupKey + " => " +
			// groupHashMap.get(groupKey));
		}
	}

	/**
	 * 生成分组极限值
	 */
	private void genLimit() {
		statusHashMap.clear();
		tempHashMap1.clear();
		tempHashMap2.clear();
		limitHashMap1.clear();
		limitHashMap2.clear();
		// System.out.println("\n开始找连续极限=>");
		System.out.println("原始记录=>" + history);
		int loopMax = startIndex + stepLen;
		for (int t = startIndex; t < loopMax; t++) {
			if (t >= history.size()) {
				break;
			}
			currentIndex = t;
			byte i = history.get(t);
			for (Entry<String, List<Byte>> m : groupHashMap.entrySet()) {
				String d = m.getKey();
				String notKey = "!" + d;

				if (!statusHashMap.containsKey(d)) {
					statusHashMap.put(d, new ArrayList<Byte>());
				}
				if (!limitHashMap1.containsKey(d)) {
					limitHashMap1.put(d, (short) 0);
				}
				if (!limitHashMap2.containsKey(notKey)) {
					limitHashMap2.put(notKey, (short) 0);
				}
				if (!tempHashMap1.containsKey(d)) {
					tempHashMap1.put(d, (short) 0);
				}
				if (!tempHashMap2.containsKey(notKey)) {
					tempHashMap2.put(notKey, (short) 0);
				}
				// System.out.println("t=" + t + "," + "i=" + i);
				if (m.getValue().contains(i)) {
					statusHashMap.get(d).add((byte) 1);
					// 第1个元素的特殊处理
					if (t == 0) {
						limitHashMap1.put(d, (short) 1);
						tempHashMap1.put(d, (short) 1);
					} else {
						if (statusHashMap.get(d).get(t - 1).equals((byte) 1)) {
							// 连续出现1
							short temp = tempHashMap1.get(d);
							temp += 1;
							short limit = limitHashMap1.get(d);
							if (temp >= limit) {
								limitHashMap1.put(d, temp);
								tempHashMap1.put(d, (short) 0);
							}
							tempHashMap1.put(d, temp);
						} else {
							// 有间断，重新计数
							tempHashMap1.put(d, (short) 1);//比如：1，1，0，1，到第4位，即1时，此时临时计数，重新认为这是第1次连续出现1
							if (limitHashMap1.get(d) <= 0) {
								limitHashMap1.put(d, (short) 1);
							}
						}
					}
				} else {
					statusHashMap.get(d).add((byte) 0);
					if (t == 0) {
						limitHashMap2.put(notKey, (short) 1);
						tempHashMap2.put(notKey, (short) 1);
					} else {
						if (statusHashMap.get(d).get(t - 1).equals((byte) 0)) {
							// 连续出现0
							short temp = tempHashMap2.get(notKey);
							temp += 1;
							short limit = limitHashMap2.get(notKey);
							if (temp >= limit) {
								limitHashMap2.put(notKey, temp);
								tempHashMap2.put(notKey, (short) 0);
							}
							tempHashMap2.put(notKey, temp);
						} else {
							// 有间断，重新计数
							tempHashMap2.put(notKey, (short) 1);
							if (limitHashMap2.get(notKey) <= 0) {
								limitHashMap2.put(notKey, (short) 1);
							}
						}
					}
				}
			}
		}

		for (Entry<String, List<Byte>> m : groupHashMap.entrySet()) {
			// System.out.println("01状态：" + m.getKey() + "=>"
			// + statusHashMap.get(m.getKey()));
			// System.out.println("正向极限: " + m.getKey() + "=>"
			// + limitHashMap1.get(m.getKey()));
			// System.out.println("反向极限: !" + m.getKey() + "=>"
			// + limitHashMap2.get("!" + m.getKey()));

			byte lastStatus = statusHashMap.get(m.getKey()).get(currentIndex);
			// System.out.println("最后一位状态：" + lastStatus);

			// 应该取反向temp极限
			if (lastStatus == 0) {
				tempHashMap1.put(m.getKey(), (short) 0);// 正向temp极限清空
			} else {
				tempHashMap2.put("!" + m.getKey(), (short) 0);// 反向temp极限清空
			}
			// System.out.println("正向temp极限: " + m.getKey() + "=>"
			// + tempHashMap1.get(m.getKey()));
			// System.out.println("反向temp极限: !" + m.getKey() + "=>"
			// + tempHashMap2.get("!" + m.getKey()));
		}

		// 找出temp与limit中相等的记录，即达到上限的正向记录
		candidateHashMap1.clear();
		candidateHashMap2.clear();
		for (Entry<String, Short> t : tempHashMap1.entrySet()) {
			for (Entry<String, Short> m : limitHashMap1.entrySet()) {
				if (t.getKey().equals(m.getKey())
						&& t.getValue().equals(m.getValue())) {
					// System.out.println("find: -> " + t);
					candidateHashMap1.put(t.getKey(), t.getValue());
				}
			}
		}

		// 找出temp与limit中相等的记录，即达到上限的反向记录
		for (Entry<String, Short> t : tempHashMap2.entrySet()) {
			for (Entry<String, Short> m : limitHashMap2.entrySet()) {
				if (t.getKey().equals(m.getKey())
						&& t.getValue().equals(m.getValue())) {
					candidateHashMap2.put(t.getKey(), t.getValue());
				}
			}
		}

		// 对候选结果进行排序
		List<Map.Entry<String, Short>> tempList = new ArrayList<Map.Entry<String, Short>>(
				candidateHashMap1.entrySet());

		Collections.sort(tempList, new Comparator<Map.Entry<String, Short>>() {
			public int compare(Map.Entry<String, Short> o1,
					Map.Entry<String, Short> o2) {
				return (o2.getValue() - o1.getValue());
			}
		});

		// 排序后
		max1 = 0;
		maxGroupName1 = "";
		if (tempList.size() > 0) {
			candidateHashMap1.clear();
			candidateHashMap1.put(tempList.get(0).getKey(), tempList.get(0)
					.getValue());
			max1 = tempList.get(0).getValue();
			maxGroupName1 = tempList.get(0).getKey();
		}

		System.out.println("正向最大极限：" + candidateHashMap1);

		tempList = new ArrayList<Map.Entry<String, Short>>(
				candidateHashMap2.entrySet());

		Collections.sort(tempList, new Comparator<Map.Entry<String, Short>>() {
			public int compare(Map.Entry<String, Short> o1,
					Map.Entry<String, Short> o2) {
				return (o2.getValue() - o1.getValue());
			}
		});

		max2 = 0;
		maxGroupName2 = "";
		if (tempList.size() > 0) {
			candidateHashMap2.clear();
			candidateHashMap2.put(tempList.get(0).getKey(), tempList.get(0)
					.getValue());
			max2 = tempList.get(0).getValue();
			maxGroupName2 = tempList.get(0).getKey();
		}

		System.out.println("反向最大极限：" + candidateHashMap2);
	}

	private PREDICT_RESULT predict() {
		nextValue = 0;
		// 比较二组最大极限，生成候选组
		int limitMax = Math.max(max1, max2);
		if (limitMax < minGroupLimit) {
			System.out.println("分组无效，请重新尝试!");
			return PREDICT_RESULT.INVALID_GROUP;
		}
		if (max1 > max2) {
			candidateGroupName = "!" + maxGroupName1;
			candidateUseLimit1 = false;
		} else {
			candidateGroupName = maxGroupName2.substring(1);
			candidateUseLimit1 = true;
		}

		if (currentIndex < history.size() - 1) {
			nextValue = history.get(currentIndex + 1);
		}

		System.out.println("\n当前索引：" + currentIndex + "，当前数："
				+ history.get(currentIndex) + "，下一个数：" + nextValue + "，下轮候选组："
				+ candidateGroupName + "，candidateUseLimit1="
				+ candidateUseLimit1);

		// 判断是否命中
		String groupKey = candidateGroupName;
		if (groupKey.indexOf("!") != -1) {
			groupKey = groupKey.substring(1);
		}

		boolean predictSuccess = false;
		List<Byte> candidateGroupValue = new ArrayList<Byte>();
		List<Byte> tempList2 = groupHashMap.get(groupKey);

		if (candidateUseLimit1) {
			candidateGroupValue = tempList2;
			
		} else {
			System.out.println(candidateGroupName.replace('!', ' ') + " => "
					+ tempList2);
			for (Byte i = 1; i <= maxNumber; i++) {
				if (!tempList2.contains(i)) {
					candidateGroupValue.add(i);
				}
			}
		}
		if (candidateGroupValue.contains(nextValue)) {
			predictSuccess = true;
		}

		System.out.println(candidateGroupName + " => " + candidateGroupValue);
		if (predictSuccess) {
			System.out.println("命中!");
			return PREDICT_RESULT.SUCCESS;
		} else {
			System.out.println("未命中!");
			return PREDICT_RESULT.FAILURE;
		}
	}

	/**
	 * 构造函数
	 * 
	 * @param startIndex
	 *            历史数据分析范围的开始索引
	 * @param stepLen
	 *            分析数据的个数(即：分析的数据为 startIndex向后数 stepLen个数字)
	 * @param randomCount
	 *            随机生成历史数据的总个数
	 * @param groupCount
	 *            对半分组方案的生成数量
	 * @param minGroupLimit
	 *            分组方案最低连续极限(低于该值，视为本轮分组无效)
	 * @param maxNumber
	 *            随机历史记录的最大值
	 * @throws Exception
	 */
	public Algorithm(int startIndex, int stepLen, int randomCount,
			int groupCount, byte minGroupLimit, byte maxNumber)
			throws Exception {

		this.startIndex = startIndex;
		this.stepLen = stepLen;
		this.randomCount = randomCount;
		this.groupCount = groupCount;
		this.minGroupLimit = minGroupLimit;
		this.maxNumber = maxNumber;

		// 初始化
		rnd = new Random();
		statusHashMap = new HashMap<String, List<Byte>>();
		limitHashMap1 = new HashMap<String, Short>();
		limitHashMap2 = new HashMap<String, Short>();
		tempHashMap1 = new HashMap<String, Short>();
		tempHashMap2 = new HashMap<String, Short>();
		candidateHashMap1 = new HashMap<String, Short>();
		candidateHashMap2 = new HashMap<String, Short>();

		genHistory();

		groupHashMap = new HashMap<String, List<Byte>>();
	}

	public PREDICT_RESULT predictFuture() {
		// 分组
		genGroup();
		// 求连续极限
		genLimit();
		// 预测
		return predict();
		// return PREDICT_RESULT.SUCCESS;
	}

	public int getStepLen() {
		return stepLen;
	}

	public void setStepLen(int stepLen) {
		this.stepLen = stepLen;
	}

}
